package sengine;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.lwjgl.input.Mouse;

/**
 *
 * @author twoodf5611
 */
public class SpriteEngine extends GLGame {
    private final List<Sprite> sprites = new ArrayList<>();
    private final List<KeyListener> keys = new ArrayList<>();
    private final LinkedList<Sprite> rmQueue = new LinkedList<>();
    private final LinkedList<Sprite> addQueue = new LinkedList<>();
    private final PhysicsEngine phys = new PhysicsEngine();
    private boolean mouseLState = false;
    private boolean mouseRState = false;
    
    @Override
    protected void render(long millis) {
        _clearRmQueue();
        if(Mouse.isButtonDown(0)) {
            if(!mouseLState) {
                mouseEvent(getView()+Mouse.getX(), Mouse.getY(), false);
                mouseLState = true;
            }
        } else {
            mouseLState = false;
        }
        if(Mouse.isButtonDown(1)) {
            if(!mouseRState) {
                mouseEvent(getView()+Mouse.getX(), Mouse.getY(), true);
                mouseRState = true;
            }
        } else {
            mouseRState = false;
        }
        for(Sprite sprite: sprites) {
            sprite.update(millis);
        }
        phys.update(millis);
        _clearRmQueue();
        for(Sprite sprite: sprites) {
            sprite.render();
        }
    }

    @Override
    protected void keyEvent(int key, boolean down) {
        for(KeyListener keyl: keys) {
            keyl.keyEvent(key, down);
        }
    }
    
    private void mouseEvent(int x, int y, boolean right) {
        for(KeyListener keyl: keys) {
            keyl.mouseDown(x, y, right);
        }
    }
    
    public void addSprite(Sprite sprite) {
        addQueue.add(sprite);
    }
    
    protected void _addSprite(Sprite sprite) {
        phys.addObject(sprite);
        sprites.add(sprite);
        sprite.setSEngine(this);
    }
    
    /**
     * Queue a sprite for removal (avoid concurrent modification issues)
     * @param sprite 
     */
    public void rmSprite(Sprite sprite) {
        rmQueue.push(sprite);
    }
    
    public void _clearRmQueue() {
        Sprite rm;
        while((rm=rmQueue.poll())!=null) {
            _rmSprite(rm);
        }
        Sprite add;
        while((add=addQueue.poll())!=null) {
            _addSprite(add);
        }
    }
    
    /**
     * Immediately remove Sprite from the engine
     * @param sprite 
     */
    protected void _rmSprite(Sprite sprite) {
        phys.removeObject(sprite);
        sprites.remove(sprite);
        sprite.setSEngine(null);
    }
    
    public void addKeyListener(KeyListener listener) {
        keys.add(listener);
    }
    
    public void rmKeyListener(KeyListener listener) {
        keys.remove(listener);
    }
    
//    public void update(){
//        
//    }
}
